#include "mod_gui.h"

#include "dev.h"
#include "log.h"
#include "platform.h"
#include "code/inc/lcd_adapter.h"
#include "utility.h"
#include "data.h"

#include <stdlib.h>
#include <stdio.h> 
#include <string.h>

#define GUI_CHARGE_GUN_CNT 2 //

void poll_yx(void);
enum GuiGunWorkState{
    GUI_GUN_WORK_IDLE = 0,
    GUI_GUN_WORK_CHARGING,
    GUI_GUN_WORK_SETTLE,
    GUI_GUN_WORK_ALARM,
};

struct GuiYx{
    uint8_t gun_work;
    uint8_t gun_link;
    uint8_t net_state;
};

struct GuiChargeInfo{
    uint32_t sec;
    uint32_t kwh;
    
};
struct GuiYc{
    struct GuiChargeInfo charge;
    
};
static uint8_t test_flag = 0;  //打印控制标志
static uint8_t gun_num = 1;
static struct GuiYx gui_yx[GUI_CHARGE_GUN_CNT] = {0};

static os_mutex_t gui_mutex = NULL;

void gui_send_msg(char_t *msg){
    if (test_flag){
        printf("gui send msg:%s len = %d\r\n", msg,strlen(msg));
    }
    os_mutex_lock(&gui_mutex);    
    lcdadapter_sendmsg(msg);
    os_mutex_unlock(&gui_mutex);
}

void gui_show_init(uint8_t gun_id){
    char_t val[200]={0};
    uint8_t dev_mode = dev_get_dev_mode();
    gun_num = data_getint("gunnum");
    char_t dev_id[20]={0};
    data_getstr("devid", dev_id, sizeof(dev_id));
    
    //init
    set_cmd_str(val, "cmd=", "guiinit");
    set_cmd_str(val, "&dev_ver=", "1.1.1.2");
    set_cmd_str(val, "&pro_ver=", "1.1.1.0");
    
    if (dev_mode == DEV_CHARGE_MODE_AC){
        set_cmd_str(val, "&dev_type=", "ac");
    }else{
        set_cmd_str(val, "&dev_type=", "dc");
    }
    set_cmd_str(val, "&dev_num=", dev_id);
    set_cmd_value(val, "&gun_num=", gun_num);

    gui_send_msg(val);
    
    //qr_wechat
		
    memset(val, 0, sizeof(val));
    set_cmd_str(val, "cmd=", "gui_update");
    set_cmd_value(val, "&gunno=", gun_id);
    set_cmd_str(val, "&type=", "qr_wechat");
    set_cmd_str(val, "&comment=", "http://weixin.qq.com/r/bSqZgffE-qqBrbPi939-");
    
    gui_send_msg(val);
    
    //qr_charging

    char_t buf[50]={0};
    data_getstr("qrcode", buf, sizeof(buf));
    strcat(buf, dev_id);
    char_t gun_str[10]={0};
    sprintf(gun_str, "%02d", gun_id);
    strcat(buf, gun_str);
    
    memset(val, 0, sizeof(val));
    set_cmd_str(val, "cmd=", "gui_update");
    set_cmd_value(val, "&gunno=", gun_id);
    set_cmd_str(val, "&type=", "qr_charging");
    set_cmd_str(val, "&comment=", buf); 

    gui_send_msg(val);    

#if 1    
    //telephone 
    memset(buf, 0, sizeof(buf));
    data_getstr("teleph", buf, sizeof(buf));
    memset(val, 0, sizeof(val));
    set_cmd_str(val, "cmd=", "gui_update");
    set_cmd_value(val, "&gunno=", 0);
    set_cmd_str(val, "&type=", "telephone");
    set_cmd_str(val, "&comment=", buf);

    lcdadapter_sendmsg(val);
    
    //web
    memset(buf, 0, sizeof(buf));
    data_getstr("web", buf, sizeof(buf));
    memset(val, 0, sizeof(val));
    set_cmd_str(val, "cmd=", "gui_update");
    set_cmd_value(val, "&gunno=", 0);
    set_cmd_str(val, "&type=", "web");
    set_cmd_str(val, "&comment=", buf);   
    
    lcdadapter_sendmsg(val);
#endif
}

void gui_show_card_select(uint8_t select_id){

}

void gui_show_reswip_card(uint8_t cnt){
    printf("please reswip card\r\n");
}

void gui_show_idle(uint8_t gun_id){
    gui_yx[gun_id-1].gun_work = GUI_GUN_WORK_IDLE;
    gui_yx[gun_id-1].gun_link = 1;
    poll_yx();
}

void gui_show_wait_gunin(uint8_t gun_id){
    gui_yx[gun_id-1].gun_work = GUI_GUN_WORK_IDLE;
    gui_yx[gun_id-1].gun_link = 0;
    poll_yx();
}

void gui_show_wait_charge(uint8_t cnt){

}

void gui_show_start_charging_fail(uint8_t gun_id, uint32_t cnt, char_t *reasion){
    
     // gui_yx[gun_id-1].gun_work = GUI_GUN_WORK_CHARGING;
     // poll_yx();
    //  gui_show_charge_end(gun_id, 0, 0, reasion);
    char val[256] = {0};
    set_cmd_str(val,"cmd=","start_auth");
    set_cmd_value(val,"&gunno=",gun_id);
    set_cmd_str(val,"&auth_type=","qrcode");
    set_cmd_str(val,"&flag=","fail");
    set_cmd_str(val,"&failreason=",reasion);
    gui_send_msg(val);
}

void gui_show_charge(uint8_t gun_id){
    printf("gui_show_charge\r\n");
    gui_yx[gun_id-1].gun_work = GUI_GUN_WORK_CHARGING;
    poll_yx();
}

void gui_update_charge_str(uint8_t gun_id, uint32_t kwh, uint32_t sec, char_t *str){    
    char_t val[300]={0};
    set_cmd_str(val, "cmd=", "dev_yc");
    set_cmd_value(val, "&gunno=", gun_id);
    set_cmd_str(val, "&yctype=", "chargeinfo");
    
    char_t sec_str[20]={0};
    if (sec < 3600){
        sprintf(sec_str, "%d分", sec/60);
    }else{
        sprintf(sec_str, "%d时%d分", sec/3600, (sec%3600)/60);    
    }

    set_cmd_str(val, "&charingtime=", sec_str);
    
    char_t kwh_str[20]={0};
    sprintf(kwh_str, "%d.%03d度", kwh/100, kwh%100);
    set_cmd_str(val, "&chargingpower=", kwh_str);
    
    uint32_t vol = dev_get_vol(gun_id);
    char_t vol_str[20]={0};
    sprintf(vol_str, "%dV", vol/100);
    set_cmd_str(val, "&outputvoltage=", vol_str);
    
    uint32_t current = dev_get_current(gun_id);
    char_t curt_str[20]={0};
    sprintf(curt_str, "%d.%02dA", current/100, current%100);
    set_cmd_str(val, "&outputcurrent=", curt_str); 
    
    set_cmd_str(val, "&devstate=", str);
    
    uint8_t dev_mode = dev_get_dev_mode();
    if (dev_mode == DEV_CHARGE_MODE_DC) {
        char_t need_vol[20]={0};
        uint32_t vol = dev_get_need_vol(gun_id);
        sprintf(need_vol, "%dV", vol/100);
        set_cmd_str(val, "&demandvoltage=", need_vol);         
        
        char_t need_currt[20]={0};
        uint32_t currt = dev_get_need_currt(gun_id);
        sprintf(need_currt, "%dA", currt/100);
        set_cmd_str(val, "&demandcurrent=", need_currt);
            
        char_t left_time[20]={0};
        uint32_t time = dev_get_left_time(gun_id);
        sprintf(left_time, "%dm", time);
        set_cmd_str(val, "&remaintime=", left_time);
        
        char_t soc_str[20]={0};
        uint32_t soc = dev_get_soc(gun_id);
        sprintf(soc_str, "%d%%", soc);
        set_cmd_str(val, "&soc=", soc_str); 
    }
    
    gui_send_msg(val);
}

void gui_update_charge(uint8_t gun_id, uint32_t kwh, uint32_t sec){
    gui_update_charge_str(gun_id, kwh, sec, "充电中");
}

void gui_show_charge_end(uint8_t gun_id, uint32_t kwh, uint32_t sec, char_t *reasion){
    gui_update_charge_str(gun_id, kwh, sec, reasion);
}

void gui_show_settle(uint8_t gun_id, int32_t tkwh, int32_t tsec, int32_t tcost, int32_t cnt){
    printf("gui_show_settle\r\n");
    gui_yx[gun_id-1].gun_work = GUI_GUN_WORK_SETTLE;
    
    poll_yx();
    
    char_t val[150]={0};
    set_cmd_str(val, "cmd=", "dev_yc");
    set_cmd_value(val, "&gunno=", gun_id);
    set_cmd_str(val, "&yctype=", "settleinfo");
    
    char_t tkwh_str[20]={0};
    sprintf(tkwh_str, "%d.%03d", tkwh/100, tkwh%100);    
    set_cmd_str(val, "&settlepower=", tkwh_str);
    
    char_t tcost_str[20]={0};
    sprintf(tcost_str, "%d.%02d", tcost/100, tcost%100);    
    set_cmd_str(val, "&settlecost=", tcost_str);
    
    char_t ttime_str[20]={0};
    if (tsec <= 60){
        sprintf(ttime_str, "%d分", 1);
    }else if (tsec < 3600){
        sprintf(ttime_str, "%d分", tsec/60);
    }else{
        sprintf(ttime_str, "%d时%d分", tsec/3600, (tsec%3600)/60);
    }
    
    set_cmd_str(val, "&settletime=", ttime_str);

    gui_send_msg(val);
}

void gui_show_alarm(uint8_t gun_id, char_t *code, char_t *desc){
    gui_yx[gun_id-1].gun_work = GUI_GUN_WORK_ALARM;
    poll_yx();
    
    char_t val[150]={0};
    set_cmd_str(val, "cmd=", "dev_yc");
    set_cmd_value(val, "&gunno=", gun_id);
    set_cmd_str(val, "&yctype=", "alarminfo");
    set_cmd_str(val, "&alarminfo=", desc);

    gui_send_msg(val);
}

void gui_show_net_state_online(void){
    for(uint8_t i=0;i<gun_num;i++){
        gui_yx[i].net_state = 1;
    }   
    poll_yx();
}

void gui_show_net_state_offline(void){
    for(uint8_t i=0;i<gun_num;i++){
        gui_yx[i].net_state = 0;
    }
    poll_yx();
}

void gui_sync_time(void){
    char_t time[20]={0};
    char_t val[100]={0};
    rtc_get_currt_time_str(time, sizeof(time));
    strcat(time,"000");
    set_cmd_str(val, "cmd=", "timesync");
    set_cmd_str(val, "&time=", time);
    set_cmd_str(val, "&opera=", "toset");   
    gui_send_msg(val);
}

void poll_yx(void){
    char_t val[200]={0};
    for(uint8_t i=0;i<gun_num;i++){
        memset(val, 0, sizeof(val));
        set_cmd_str(val, "cmd=", "dev_yx");
        set_cmd_value(val, "&gunno=", i+1);
        
        if (gui_yx[i].gun_work == GUI_GUN_WORK_IDLE){
            set_cmd_str(val, "&gunstate=", "idle");
        }else if(gui_yx[i].gun_work == GUI_GUN_WORK_CHARGING){
            set_cmd_str(val,"&gunstate=", "charging");
        }else if (gui_yx[i].gun_work == GUI_GUN_WORK_SETTLE){
            set_cmd_str(val,"&gunstate=", "settle");
        }else if (gui_yx[i].gun_work == GUI_GUN_WORK_ALARM){
            set_cmd_str(val,"&gunstate=", "alarm");
        }else{
         //
        }
        
        if (gui_yx[i].gun_link == 0){
            set_cmd_str(val,"&connectstate=", "connectnone");
        }else{
            set_cmd_str(val,"&connectstate=", "connect");
        }
        if (gui_yx[i].net_state == 0){
            set_cmd_str(val, "&netstate=", "netoff");
        }else{
            set_cmd_str(val, "&netstate=", "neton");
        }
        
        gui_send_msg(val);        
    }
}

void poll_net_state(void){
    static uint8_t state = 0;
    uint8_t state_tmp = dev_get_net_state();
    if (state != state_tmp){
        state = state_tmp;
        if (state){
            gui_show_net_state_online();
        }else{
            gui_show_net_state_offline();    
        }
    }
}

void gui_set_test_flag(uint8_t state){
    test_flag = state;
}

typedef void (*gui_recv)(char *promsg);

void deal_guirecv_yk(char *msg)
{
	
	char type[32] = {0};
	char gunno[10] = {0};
  GetCmdStr((char *)msg, "yk_type", type,sizeof(type));
	GetCmdStr((char *)msg, "gunno", gunno,sizeof(gunno));
	
  if (0 == strncmp(type,"stopcharge",strlen(type))){
	 charger_stop_charge_by_user(atoi(gunno));
	}
}

struct t_cmdackinfo {
    char *cmd;
    gui_recv func;
};
const static struct t_cmdackinfo _gui_cmd_ack_info[]={
	{"gui_yk",deal_guirecv_yk},
};

gui_recv get_guirecv_deal(char *cmd)
{
	for(uint32_t i = 0;i<sizeof(_gui_cmd_ack_info)/sizeof(struct t_cmdackinfo);i++){
		char *pgetcmd = _gui_cmd_ack_info[i].cmd;
		if (0 == strncmp(pgetcmd,cmd,strlen(pgetcmd))){
			  return _gui_cmd_ack_info[i].func;
		}
	}
	return 0;
}

void gui_poll_recv(void){
    char_t recv[512]={0};
    
    if (!lcdadapter_recvmsg(recv)){
			 return ;
		}
    //printf("gui recv msg:%s\r\n", recv);
      
		char cmd[32] = {0};
    GetCmdStr((char *)recv, "cmd", cmd,sizeof(cmd));
    if(!strlen(cmd)){
           return ;
    }
	  //printf("cmd recv = %s\r\n",cmd);
    gui_recv recvdeal = get_guirecv_deal(cmd);
		if(recvdeal){
			(recvdeal)(recv);
		}
	
}

static void gui_task(void *para){
    static uint32_t cnt = 0;

    while(1){
        lcdadapter_poll();        
        if (cnt %20 == 0){
            gui_poll_recv();
            poll_net_state();
        }  
        os_msleep(10);
    }
}

int32_t gui_init(void){  
    os_pthread_t gui_thread;
    gui_mutex = os_mutex_create();
    lcdadapter_init();
    
    if (os_pthread_create("gui", &gui_thread, gui_task, NULL,  OS_TASK_PRIO_LOW, OS_STACK_SIZE_SUPER_LARGE) != 0){
        return -1;
    }    
    return 0;
}

